// /*
//  * @Author: WanYiMing
//  * @Date:2024-03-11-18:04
//  * @Description:
//  */

using System;
using System.Collections.Generic;
using UnityEngine;

namespace Code.Controller.Component.TimeTask
{
    public class TimeSysManager : MonoBehaviour
    {
        private static TimeSysManager _instance;

        public static TimeSysManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new GameObject("TimeSysManager").AddComponent<TimeSysManager>();
                }

                return _instance;
            }
            set
            {
                if (_instance == null)
                {
                    _instance = value;
                }
            }
        }

        public void Start()
        {
            Instance = this;
        }

        private List<TimerTask> _timerTasks = new List<TimerTask>();
        private List<FrameTask> _frameTasks = new List<FrameTask>();
        private List<int> _tIDs = new List<int>();
        private int _tID;
        private static readonly string Obj = "lock";
        private int _frame;

        private void Update()
        {
            _frame++;
            TimeFunc();
            FrameFunc();
        }

        private void TimeFunc()
        {
            for (int i = 0; i < _timerTasks.Count; i++)
            {
                
                if (_timerTasks[i].BsetTime < UnityEngine.Time.realtimeSinceStartup * 1000)
                {
                    if (_timerTasks[i].Callback != null)
                    {
                        _timerTasks[i].Callback();
                        _timerTasks[i].BsetTime = UnityEngine.Time.realtimeSinceStartup * 1000f + _timerTasks[i].DelayTime;
                        if (_timerTasks[i].CurrNum == -1)
                        {
                            continue;
                        }
                        else
                        {
                            _timerTasks[i].CurrNum--;
                            if (_timerTasks[i].CurrNum == 0)
                            {
                                _timerTasks.RemoveAt(i);
                                i--;
                            }
                        }
                    }
                }
            }
        }

        private void FrameFunc()
        {
            for (int i = 0; i < _frameTasks.Count; i++)
            {
                if (_frameTasks[i].BsetTime < _frame)
                {
                    if (_frameTasks[i].Callback != null)
                    {
                        _frameTasks[i].Callback();
                        _frameTasks[i].BsetTime = _frame + _frameTasks[i].DelayTime;
                        if (_frameTasks[i].CurrNum == -1)
                        {
                            continue;
                        }
                        else
                        {
                            _frameTasks[i].CurrNum--;
                            if (_frameTasks[i].CurrNum == 0)
                            {
                                _frameTasks.RemoveAt(i);
                                i--;
                            }
                        }
                    }
                }
            }
        }

        #region 时间相关

        /// <summary>
        /// 
        /// </summary>
        /// <param name="delayTime"></param>
        /// <param name="action"></param>
        /// <param name="timeType"></param>
        /// <param name="num">-1为无限循环,其余整数为循环次数</param>
        public int AddTimerTask(float delayTime, Action action, TimeType timeType = TimeType.Millisecond, int num = 1)
        {
            if (timeType != TimeType.Millisecond)
            {
                switch (timeType)
                {
                    case TimeType.Second:
                        delayTime *= 1000;
                        break;
                    case TimeType.Minute:
                        delayTime *= 60;
                        break;
                    case TimeType.Hour:
                        delayTime *= 3600;
                        break;
                    case TimeType.Day:
                        delayTime *= (3600 * 24);
                        break;
                    default:
                        break;
                }
            }

            int id = GetTID();
            TimerTask timerTask = new TimerTask
            {
                BsetTime = UnityEngine.Time.realtimeSinceStartup * 1000f + delayTime, Callback = action, CurrNum = num,
                DelayTime = delayTime
            };
            timerTask.Tid = id;
            _timerTasks.Add(timerTask);
            _tIDs.Add(id);
            return timerTask.Tid;
        }

        public bool DelTimerTask(int tID)
        {
            bool isSucced = false;
            for (int i = 0; i < _timerTasks.Count; i++)
            {
                if (_timerTasks[i].Tid == tID)
                {
                    _timerTasks.RemoveAt(i);
                    isSucced = true;
                    _tIDs.Remove(tID);
                    break;
                }
            }

            return isSucced;
        }

        public bool RepTimerTask(int tID, float delayTime, Action action, TimeType timeType = TimeType.Millisecond,
            int num = 1)
        {
            bool isSucced = false;
            for (int i = 0; i < _timerTasks.Count; i++)
            {
                if (_timerTasks[i].Tid == tID)
                {
                    if (timeType != TimeType.Millisecond)
                    {
                        switch (timeType)
                        {
                            case TimeType.Second:
                                delayTime *= 1000;
                                break;
                            case TimeType.Minute:
                                delayTime *= 60;
                                break;
                            case TimeType.Hour:
                                delayTime *= 3600;
                                break;
                            case TimeType.Day:
                                delayTime *= (3600 * 24);
                                break;
                            default:
                                break;
                        }
                    }

                    TimerTask timerTask = new TimerTask
                    {
                        BsetTime = UnityEngine.Time.realtimeSinceStartup * 1000f + delayTime, Callback = action, CurrNum = num,
                        DelayTime = delayTime
                    };
                    timerTask.Tid = GetTID();
                    _timerTasks[i] = timerTask;
                    isSucced = true;
                }
            }

            return isSucced;
        }

        #endregion


        #region 帧相关

        public int AddFrameTimerTask(int delayTime, Action action, int num = 1)
        {
            int id = GetTID();
            FrameTask timerTask = new FrameTask
                { BsetTime = _frame + delayTime, Callback = action, CurrNum = num, DelayTime = delayTime };
            timerTask.Tid = id;
            _frameTasks.Add(timerTask);
            _tIDs.Add(id);
            return timerTask.Tid;
        }

        public bool DelFrameTimerTask(int tID)
        {
            bool isSucced = false;
            for (int i = 0; i < _frameTasks.Count; i++)
            {
                if (_frameTasks[i].Tid == tID)
                {
                    _frameTasks.RemoveAt(i);
                    isSucced = true;
                    _tIDs.Remove(tID);
                    break;
                }
            }

            return isSucced;
        }

        public bool RepFrameTimerTask(int tID, int delayTime, Action action, int num = 1)
        {
            bool isSucced = false;
            for (int i = 0; i < _frameTasks.Count; i++)
            {
                FrameTask timerTask = new FrameTask
                    { BsetTime = _frame + delayTime, Callback = action, CurrNum = num, DelayTime = delayTime };
                timerTask.Tid = GetTID();
                _frameTasks[i] = timerTask;
                isSucced = true;
            }

            return isSucced;
        }

        #endregion

        #region 通用生成ID

        private int GetTID()
        {
            lock (Obj)
            {
                _tID++;

                while (true)
                {
                    if (_tID == int.MaxValue)
                    {
                        _tID = 0;
                    }

                    bool used = false;
                    for (int i = 0; i < _tIDs.Count; i++)
                    {
                        if (_tIDs[i] == _tID)
                        {
                            used = true;
                            break;
                        }
                    }

                    if (!used)
                    {
                        break;
                    }

                    _tID++;
                }
            }

            return _tID;
        }

        #endregion
    }
}